#ifndef __SESSION_H__
#define __SESSION_H__

#include <atomic>
#include <boost/asio.hpp>

#include <cstdint>
#include <memory>
#include <queue>
#include <mutex>

#include "net_global.h"
#include "message_node.hpp"


class Server;

class Session: public std::enable_shared_from_this<Session>
{
public:
    using ptr = std::shared_ptr<Session>;
    using IOContext = boost::asio::io_context;
    using Tcp = boost::asio::ip::tcp;

    Session(IOContext& io_context, Server* server);
    ~Session();

    void start();
    void close();
    void send(const char* data, size_t len, uint16_t id);

    Tcp::socket& socket() { return _socket; }
    std::string uuid() const { return _uuid; }
private:
    void handle_wirte(const boost::system::error_code& error, size_t bytes_transferred, Session::ptr self);

private:
    std::string _uuid;
    IOContext& _io_context;
    Tcp::socket _socket;
    Server* _server;
    std::atomic_bool _is_closing;
    
    std::mutex _send_mutex;
    std::queue<SendNode::ptr> _send_queue;
    RecvNode::ptr _recv_node;
    MsgNode::ptr _head_node;
};


class Task 
{
public:
    using ptr = std::shared_ptr<Task>;

    Task(Session::ptr session, RecvNode::ptr recv_node)
    :_session(session), _recv_node(recv_node) {}

    uint16_t msg_id() { return _recv_node->_msg_id; }

    Session::ptr _session;
    RecvNode::ptr _recv_node;
};

#endif // !__SESSION_H__
